package calvin.controller.queue;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.mail.Message;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;

import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.slim3.controller.Controller;
import org.slim3.controller.Navigation;
import org.slim3.datastore.Datastore;

import calvin.datastore.model.Rate5s;
import calvin.utils.DateUtil;
import calvin.utils.RateHelper;

import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.taskqueue.Queue;
import com.google.appengine.api.taskqueue.QueueFactory;
import com.google.appengine.api.taskqueue.TaskOptions;

public class FetchRate5sController extends Controller {

    private static final Logger logger = Logger.getLogger(RateHelper.class
        .getName());

    private static int LOOP_COUNT = 15;
    public static int LOOP_INTERVAL = 30000;

    @Override
    public Navigation run() throws Exception {
        int count = 0;
        while (count < LOOP_COUNT) {
            long c1 = System.currentTimeMillis();
            putRate();
            long c2 = System.currentTimeMillis();
            if(c2 - c1 > LOOP_INTERVAL) {
                logger.log(Level.WARNING, "process time over 30 senconds ..");
                count++;
                continue;
            }
            Thread.sleep(LOOP_INTERVAL + c1 - c2);
            count++;
        }
        Queue queue = QueueFactory.getQueue("rate-fetch-1m-queue");
        queue.add(TaskOptions.Builder.withUrl("/queue/fetchRate5s"));

        return null;
    }

    @Override
    public Navigation handleError(Throwable t) {
        Properties props = new Properties();
        Session session = Session.getDefaultInstance(props, null);

        try {
            Message msg = new MimeMessage(session);
            msg.setFrom(new InternetAddress("calvin.helloworld@gmail.com", "Admin"));
            msg.addRecipient(Message.RecipientType.TO,
                             new InternetAddress("calvin.helloworld@gmail.com", "Calvin"));
            msg.setSubject("["+ RateHelper.APP_ID +"]Error occurred, queue is terminated abruptly");
            msg.setText(t.getMessage());
            Transport.send(msg);
    
        } catch (Exception e) {
            logger.log(
                Level.SEVERE,
                "failed to send alert mail to Calvin." + e.getMessage());
        } finally {
            logger.log(
                Level.SEVERE,
                "error occurred, queue is terminated abruptly .." + t.getMessage()); 
        }

        return null;
    }

    private void putRate() throws Exception {
        String s = RateHelper.get();

        JSONParser parser = new JSONParser();
        JSONObject obj = (JSONObject) parser.parse(s);
        JSONArray array = (JSONArray) obj.get("rate");
        for (Object o : array) {
            JSONObject json = (JSONObject) o;
            Rate5s rate = new Rate5s();
            String cp = (String) json.get("currency_pair");
            if(!RateHelper.WATCH_SET.contains(cp)) {
                continue;
            }
            double bid = Double.valueOf((String) json.get("bid"));
            rate.setCp(cp);
            rate.setV(bid);
            Calendar c =
                Calendar.getInstance(DateUtil.getTimeZone());
            c.setTimeInMillis(Long.parseLong((String) json.get("timestamp")));
            rate.setT(c.getTime());
            SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd HH:mm:ss");
            String time = sdf.format(c.getTime());
            Key key = Datastore.createKey(Rate5s.class, cp + time);
            rate.setKey(key);
            Datastore.put(rate);
        }
    }
}
